/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.specific.sge.qbase;

import java.util.Collection;

import jp.aist.gtrc.plus.reserve.*;
import jp.aist.gtrc.plus.scheduler.ScheduleStarter;
import jp.aist.gtrc.plus.scheduler.SchedulerOptions;
import jp.aist.gtrc.plus.scheduler.node.NodeAllocator;
import jp.aist.gtrc.plus.scheduler.node.NodeManager;
import jp.aist.gtrc.plus.scheduler.specific.sge.status.SGEQInstance;
import jp.aist.gtrc.plus.scheduler.status.QInstanceStatus;
import jp.aist.gtrc.plus.scheduler.status.QueueStatus;
import jp.aist.gtrc.plus.scheduler.util.CmdUtil;
import jp.aist.gtrc.plus.scheduler.util.TextUtil;


public class SGEQbaseReserveManager extends QbaseReserveManager {

	public SGEQbaseReserveManager(NodeManager nodeMgr, ScheduleStarter starter,
			ReserveRecorder recorder, NodeAllocator nodeAllocator,
			SGEQbaseStatusManager statusMgr, SchedulerOptions options) throws ReserveException {

		super(nodeMgr, starter, recorder, nodeAllocator, statusMgr, options);

	}

	protected ReserveInfo newReserveInfo(ReserveId rsvId, ReserveRequest rsvReq,
			ReserveNodeSet rsvNodeSet) throws ReserveException {

		return new SGEQbaseReserveInfo(rsvId, rsvReq, rsvNodeSet, this);

	}

	protected void addNewReserveInfo(ReserveInfo rsvInfo) throws ReserveException {

		super.addNewReserveInfo(rsvInfo);

		SGEQbaseReserveInfo info = (SGEQbaseReserveInfo)rsvInfo;
		SGEQbaseStatusManager sgeSMgr = (SGEQbaseStatusManager)getStatusManager();

		ReserveRequest req = rsvInfo.getReserveRequest();
		int slotnum = req.getOptions().getSlotNum();
		String slotnumList;
		if (slotnum > 0) {
			slotnumList = Integer.toString(slotnum);
		} else {
			slotnumList = info.getSlotNumList();
		}

		/*
		 *  usage: sge_rsvq_new.sh RSVID SLOTPERNODE USERLIST PE PREPOSTQ
		 */
		CmdUtil.runCommand(new String[] {
				"sge_rsvq_new.sh",
				info.getReserveId().toString(),
				slotnumList,
				TextUtil.fromArray(info.getUsers(), ","),
				sgeSMgr.getPENames(),
				Boolean.toString(rsvInfo.getOptions().isMakePrePostQueue())
		});

	}

	protected final void operateQInstances(
			Collection<QInstanceStatus> qinsList, boolean toSuspend) {

		if (qinsList.isEmpty()) {
			return;
		}

		String[] cmds = new String[2 + qinsList.size()];
		cmds[0] = "qmod";
		cmds[1] = (toSuspend ? "-sq" : "-usq");
		int i = 2;
		for (QInstanceStatus qins : qinsList) {
			SGEQInstance sgeQins = (SGEQInstance)qins;
			cmds[i] = sgeQins.getFullName();
			i++;
		}

		try {
			CmdUtil.runCommand(cmds);
		} catch (ReserveException e) {
			// ignore to continue
		}

	}
	protected void resumeQInstances(Collection<QInstanceStatus> qinsList) {
		operateQInstances(qinsList, false);
	}

	protected void suspendQInstances(Collection<QInstanceStatus> qinsList) {
		operateQInstances(qinsList, true);
	}

	public boolean hasRunningJobs(QueueStatus q) {

		for (QInstanceStatus qi : q.getAllQInstances()) {
			if (qi.getUsedSlotNum() > 0) {
				return true;
			}
		}
		return false;

	}

	protected boolean hasJobToRun(QueueStatus q) {

		SGEQbaseStatusManager sgeSMgr = (SGEQbaseStatusManager)getStatusManager();
		return (hasRunningJobs(q) || sgeSMgr.hasPendingJobs(q));

	}

	protected void startReservePeriod(ReserveInfo info, Phase phase) throws ReserveException {

		String[] nodes = info.getReservedNodeNames();
		String rsvNodes = TextUtil.fromArray(nodes, " ");

		CmdUtil.runCommand(new String[]{
				"sge_rsvq_start_rsv.sh",
				info.getReserveId().toString(),
				Integer.toString(phase.getPhase()),
				rsvNodes});

	}

	protected void finishReservePeriod(ReserveInfo info, Phase phase) throws ReserveException {

		CmdUtil.runCommand(new String[]{
				"sge_rsvq_del.sh",
				info.getReserveId().toString(),
				Integer.toString(phase.getPhase())});

	}

	protected void deleteQueue(ReserveInfo info, String qname) throws ReserveException {
		CmdUtil.runCommand(new String[]{"qconf", "-dq", qname});
	}

	protected void resumeQueue(ReserveInfo info, String qname) throws ReserveException {
		CmdUtil.runCommand(new String[]{"qmod", "-usq", qname});
	}

}
